package hmac

import (
	"bytes"
	"fmt"
	"sync"
)

var ClientToServer chan []byte
var ServerToClient chan []byte

var WG sync.WaitGroup

func Client(key []byte, algorithm int) error {
	name := "client"
	p := NewCTX(algorithm)
	p.Init(key)
	fmt.Printf("%s : HMAC inited\n", name)

	text := []byte("(HTTP REQUEST BODY)I need a video from bilibili")
	tail := []byte("~~~")
	p.Update(text)
	mac, _ := p.Final()
	m1 := append(text, tail...)
	m1 = append(m1, mac...)
	ClientToServer <- m1
	fmt.Printf("%s : -> server message sent with HMAC attached\n", name)

	p.ReInit()
	fmt.Printf("%s : waiting for respond\n", name)
	respond := <-ServerToClient
	text, server_mac, err := parseMessage(respond)
	if err != nil {
		WG.Done()
		return fmt.Errorf("%s : %v\n", name, err)
	}
	p.Update(text)
	mac, _ = p.Final()
	fmt.Printf("%s : get respond, checking hmac\n", name)
	if !bytes.Equal(server_mac, mac) {
		WG.Done()
		return fmt.Errorf("%s : channel is not safe", name)
	}
	p.Free()

	WG.Done()
	return nil
}

func Server(key []byte, algorithm int) error {
	name := "server"
	p := NewCTX(algorithm)
	p.Init(key)
	fmt.Printf("%s : HMAC inited\n", name)

	fmt.Printf("%s : waiting for requests\n", name)
	q1 := <-ClientToServer
	text, mac, err := parseMessage(q1)
	if err != nil {
		WG.Done()
		return fmt.Errorf("%s : %v\n", name, err)
	}
	p.Update(text)
	server_mac, _ := p.Final()
	fmt.Printf("%s : get request, checking hmac\n", name)
	if !bytes.Equal(server_mac, mac) {
		WG.Done()
		return fmt.Errorf("%s : channel is not safe\n", name)
	}

	text = []byte("(HTTP RESPOND BODY)Here's a main page, pick up what you want")
	tail := []byte("~~~")
	p.ReInit()
	p.Update(text)
	m1 := append(text, tail...)
	server_mac, _ = p.Final()
	m1 = append(m1, server_mac...)
	ServerToClient <- m1
	fmt.Printf("%s : -> client message sent with HMAC attached\n", name)
	p.Free()

	WG.Done()
	return nil
}

func parseMessage(message []byte) ([]byte, []byte, error) {
	parts := bytes.Split(message, []byte("~~~"))

	if len(parts) != 2 {
		return nil, nil, fmt.Errorf("invalid message format")
	}

	// 提取 text 和 hmac
	text := parts[0]
	hmac := parts[1]

	return text, hmac, nil
}
